package net.paoding.rose.jade.config;

import net.paoding.rose.jade.cache.JadeCache;
import net.paoding.rose.jade.cache.impl.CaffeineCache;
import net.paoding.rose.jade.cache.impl.LocalCache;
import net.paoding.rose.jade.constant.JadeConstant;
import net.paoding.rose.jade.properties.JadeDatasourceProperties;
import net.paoding.rose.jade.properties.RoseJadeProperties;
import net.paoding.rose.jade.statement.Statement;
import net.paoding.rose.jade.statement.interpreter.Interpreter;
import net.paoding.rose.jade.statement.interpreter.Jexl3Interpreter;
import net.paoding.rose.jade.statement.jexl.Jexl3Constant;
import net.paoding.rose.jade.statement.jexl.analysis.Analysis;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * @author zhangfusheng
 * @date 2023/5/9
 */
@EnableConfigurationProperties({RoseJadeProperties.class, JadeDatasourceProperties.class})
public class JadeConfig {

    private final RoseJadeProperties roseJadeProperties;

    public JadeConfig(RoseJadeProperties roseJadeProperties) {
        this.roseJadeProperties = roseJadeProperties;
        JadeConstant.CONNECTION_INDEX_FLAG = roseJadeProperties.getIndexVariableKey();
    }

    @Bean("jadeMethodStatementCache")
    @ConditionalOnClass(name = {"com.github.benmanes.caffeine.cache.Caffeine"})
    public JadeCache<Method, Statement> jadeCaffeineCache() {
        return new CaffeineCache<>(roseJadeProperties);
    }

    @Bean("jadeMethodStatementCache")
    @ConditionalOnMissingClass("com.github.benmanes.caffeine.cache.Caffeine")
    public JadeCache<Method, Statement> jadeLocalCache() {
        return new LocalCache<>();
    }

    @Bean("jadeSqlAnalysisCache")
    @ConditionalOnClass(name = {"com.github.benmanes.caffeine.cache.Caffeine"})
    public JadeCache<String, List<Analysis>> jadeSqlCaffeineCache() {
        return new CaffeineCache<>(roseJadeProperties);
    }

    @Bean("jadeSqlAnalysisCache")
    @ConditionalOnMissingClass("com.github.benmanes.caffeine.cache.Caffeine")
    public JadeCache<String, List<Analysis>> jadeSqlLocalCache() {
        return new LocalCache<>();
    }

    @Bean
    @ConditionalOnProperty(value = "jade.config.use-jexl3-interpreter", havingValue = "true")
    public Interpreter jexl3Interpreter(
            @Qualifier("jadeSqlAnalysisCache") JadeCache<String, List<Analysis>> jadeSqlAnalysisCache) {
        return new Jexl3Interpreter(jadeSqlAnalysisCache);
    }

    /**
     * 注册 namespace
     * @param namespace
     */
    public void registerNamespace(Map<String, Object> namespace) {
        Jexl3Constant.JEXL3_BUILDER_NAME_SPACE.putAll(namespace);
    }
}
